package cn.iocoder.yudao.adminserver.franky.LRU;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description:
 * @Author: franky
 * @CreateDate: 2021/4/15 3:51 下午
 * @Version: 1.0
 */
public class LRUNode3 {

    private Integer capacity;
    private Map<String, Node3> lruMap;
    private Node3 head;
    private Node3 end;

    public LRUNode3(Integer capacity) {
        this.capacity = capacity;
        lruMap = new ConcurrentHashMap<>();
    }

    public String get(String key) {
        if (!lruMap.containsKey(key))
            return null;
        Node3 node = lruMap.get(key);
        refreshNode(node);
        return node.value;
    }


    public void add(String key, String value) {
        Node3 node = lruMap.get(key);
        if (node == null) {
            //如果是新插入的，则需要判断是否回收
            if (lruMap.size() >= capacity) {
                lruMap.remove(head.key);
                removeNode(head);
            }
            node = new Node3(key, value);
            addNode(node);
            lruMap.put(key, node);
        } else {
//            removeNode(node);
//            addNode(node);
            node.value = value;
            refreshNode(node);
        }
    }

    public void remove(String key) {
        Node3 node = lruMap.get(key);
        if (null != node) {
            lruMap.remove(key);
            removeNode(node);
        }
    }

    private void refreshNode(Node3 node) {
        if (end == node) {
            return;
        }
        removeNode(node);
        addNode(node);
    }

    private void addNode(Node3 node) {
        if (end != null) {
            end.next = node;
            node.pre = end;
            node.next = null;
        }
        end = node;
        if (head == null) {
            head = node;
        }
    }

    private void removeNode(Node3 node) {
        if (head == node && end == node) {
            head = null;
            end = null;
        } else if (head == node) {
//            head.next.pre = null;
            head = head.next;
            head.pre = null;
        } else if (end == node) {
            end = end.next;
            end.next = null;
        } else {
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }
    }


    private class Node3 {
        private String key;
        private String value;
        private Node3 pre;
        private Node3 next;


        public Node3(String key, String value) {
            this.key = key;
        }
    }

}
